package com.buhler.iot;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.setting.dialect.Props;
import com.buhler.iot.entity.ScriptEntity;
import com.buhler.iot.task.WriteTask;
import com.google.common.collect.Queues;

import com.xxdb.DBConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Set;
import java.util.List;
import java.util.concurrent.*;

/**
 * 启动入口类
 */
public class App {
    static Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        Props prop = new Props("config.txt");

        int[] rounds = {  1000};

        for (int size : rounds) {
            executeBatchInsert(size, prop);
        }
    }


    public static void executeBatchInsert(int size, Props prop) {
        DBConnection connection = new DBConnection();
        String host = prop.getStr("host");
        Integer port = prop.getInt("port");
        String userId = prop.getStr("userId");
        String password = prop.getStr("password");
        try {
            logger.info("preparing data ");
            ScriptGenerator generator = new ScriptGenerator(size);
            Set<ScriptEntity> sets = generator.generate();


            logger.info("prepared data with {} rows data each table", size);
            connection.connect(host, port, userId, password);
            logger.info("connecting to dolphindb {}:{} with account:{},password:{}", host, port, userId, password);

            LocalDateTime startTime = LocalDateTime.now();
            logger.info("begin batch insert data");

            for (int round = 0; round < 50; round++) {
                batchInsert(connection, Queues.newConcurrentLinkedQueue(sets));
            }

            LocalDateTime endTime = LocalDateTime.now();
            java.time.Duration duration = java.time.Duration.between(startTime, endTime);
            logger.info("end of batch insert data for 50 rounds.\n every table have {} rows data in each round, total elapse {} ms", size, duration.toMillis());

        } catch (Exception exception) {
            exception.printStackTrace();
            logger.error(exception.getMessage());
        } finally {
            connection.close();
        }
    }


    private static void batchInsert(DBConnection connection, ConcurrentLinkedQueue<ScriptEntity> scriptQueue) throws InterruptedException, ExecutionException, TimeoutException {
        ThreadPoolExecutor threadPoolExecutor = ThreadUtil.newExecutor(21, 21);
        List<Future<?>> rets = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            rets.add(threadPoolExecutor.submit(new WriteTask(connection, scriptQueue)));
        }

        for (Future<?> submit : rets) {
            submit.get(60, TimeUnit.SECONDS);
        }
        threadPoolExecutor.shutdown();
    }
}